// Kony


#include "UI/ViewModel/MVVM_LoadScreen.h"

#include "Game/BaseGameInstance.h"
#include "Game/Base_GameModeBase.h"
#include "Kismet/GameplayStatics.h"
#include "UI/ViewModel/MVVM_LoadSlot.h"

//初始化函数
void UMVVM_LoadScreen::InitializeLoadSlots()
{
	//创建加载槽
	LoadSlot_0 = NewObject<UMVVM_LoadSlot>(this,LoadSlotViewModelClass);
	LoadSlot_0->SetLoadSlotName(FString("LoadSlot_0")); //设置槽位名称
	LoadSlot_0->SlotIndex = 0;//设置槽位索引
	LoadSlot_1 = NewObject<UMVVM_LoadSlot>(this,LoadSlotViewModelClass);
	LoadSlot_1->SetLoadSlotName(FString("LoadSlot_1")); //设置槽位名称
	LoadSlot_1->SlotIndex = 1;
	LoadSlot_2 = NewObject<UMVVM_LoadSlot>(this,LoadSlotViewModelClass);
	LoadSlot_2->SetLoadSlotName(FString("LoadSlot_2")); //设置槽位名称
	LoadSlot_2->SlotIndex = 2;
	LoadSlots.Add(0,LoadSlot_0);
	LoadSlots.Add(1,LoadSlot_1);
	LoadSlots.Add(2,LoadSlot_2);
	//设置加载槽的总数
	SetNumLoadSlots(LoadSlots.Num());
}
//通过索引获取对应槽位
UMVVM_LoadSlot* UMVVM_LoadScreen::GetLoadSlotViewModelByIndex(const int32 Index) const
{
	return LoadSlots.FindChecked(Index);
}
//添加新游戏按钮函数
void UMVVM_LoadScreen::NewGameButtonPressed(int32 Slot)
{
	LoadSlots[Slot]->SetWidgetSwitcherIndex.Broadcast(1);
}
//添加新槽位按钮函数 需要携带角色昵称
void UMVVM_LoadScreen::NewSlotButtonPressed(int32 Slot, const FString& EnteredName)
{
	//从游戏静态数据中 获取游戏模式
	ABase_GameModeBase* BaseGameMode = Cast<ABase_GameModeBase>(UGameplayStatics::GetGameMode(this));
	LoadSlots[Slot]->SlotStatus = ESaveSlotStatus::Taken; //设置槽位已占用状态
	LoadSlots[Slot]->SetPlayerName(EnteredName); //设置玩家昵称 内部会广播数据到界面
	LoadSlots[Slot]->SetMapName(BaseGameMode->DefaultMapName);//设置首次创建角色为默认地图名称，游戏中需要用其他方式写入
	LoadSlots[Slot]->SetPlayerLevel(1); //设置玩家等级 默认1
	LoadSlots[Slot]->PlayerStartTag = BaseGameMode->DefaultPlayerStartTag; //设置玩家起始标签
	//调用保存槽位数据函数
	BaseGameMode->SaveSlotGame(LoadSlots[Slot],Slot);
	//调用初始化槽位 这里面会处理数据根据状态 调用广播切换组件
	LoadSlots[Slot]->InitializeSlot();

	//从游戏模式中 获取游戏实例
	UBaseGameInstance* BaseGameInstance = Cast<UBaseGameInstance>(BaseGameMode->GetGameInstance());
	BaseGameInstance->LoadSlotName = LoadSlots[Slot]->GetLoadSlotName(); //设置加载槽名称
	BaseGameInstance->LoadSlotIndex = LoadSlots[Slot]->SlotIndex; //设置加载槽索引
	BaseGameInstance->PlayerStartTag = BaseGameMode->DefaultPlayerStartTag; //设置玩家起始点 为游戏模式蓝图设置的玩家起始点
}
//添加选择角色槽位按钮函数
void UMVVM_LoadScreen::SelectSlotButtonPressed(int32 Slot)
{
	//广播此槽位被选中 用于触发主界面的按钮更新
	LoadSlotSelected.Broadcast();
	
	//这部分是广播给每个槽位的槽位更新状态
	//循环所有槽位
	for (const TTuple<int32,UMVVM_LoadSlot*> LoadSlot : LoadSlots)
	{
		//如果是选中的按钮 
		if (LoadSlot.Key == Slot)
		{
			//则广播false 禁用按钮
			LoadSlot.Value->EnableSelectSlotButton.Broadcast(false);
		}
		else
		{
			//不是则广播true 启用按钮
			LoadSlot.Value->EnableSelectSlotButton.Broadcast(true);
		}
	}
	//存储选中的槽位 到变量 用于后续删除等操作
	SelectedSlot = LoadSlots[Slot];
}
//删除按钮点击事件
void UMVVM_LoadScreen::DeleteButtonPressed()
{
	//如果选中了存档
	if (IsValid(SelectedSlot)){
		//从内存中删除存档
		ABase_GameModeBase::DeleteSaveSlot(SelectedSlot->GetLoadSlotName(), SelectedSlot->SlotIndex);
		//设置槽位状态为空置状态,并初始化为默认空槽位
		SelectedSlot->SlotStatus = Vacant;
		SelectedSlot->InitializeSlot();
		//启用选择存档操按钮
		SelectedSlot->EnableSelectSlotButton.Broadcast(true);
	}
}
//选择槽位索引 开始游戏
void UMVVM_LoadScreen::PlayButtonPressed()
{
	
	ABase_GameModeBase* BaseGameMode = Cast<ABase_GameModeBase>(UGameplayStatics::GetGameMode(this));
	if (!BaseGameMode)
	{
		// 游戏模式未设置或类型不匹配，直接返回避免崩溃
		return;
	}
	//获取从GameMode中游戏实例
	UBaseGameInstance* BaseGameInstance = Cast<UBaseGameInstance>(BaseGameMode->GetGameInstance());
	//从选择的存档中 取出玩家最后一次所在位置，设置游戏实例玩家起始点标签
	BaseGameInstance->PlayerStartTag = SelectedSlot->PlayerStartTag;
	BaseGameInstance->LoadSlotName = SelectedSlot->GetLoadSlotName(); //保存槽位名称到游戏实例
	BaseGameInstance->LoadSlotIndex = SelectedSlot->SlotIndex; //保存槽位索引到游戏实例
	//检测是否选择了槽位
	if (IsValid(SelectedSlot))
	{
		//跳转地图
		BaseGameMode->TravelToMap(SelectedSlot);
	}
}

//加载存档数据
void UMVVM_LoadScreen::LoadData()
{
	//获取游戏模式
	ABase_GameModeBase* BaseGameMode = Cast<ABase_GameModeBase>(UGameplayStatics::GetGameMode(this));
	if (!BaseGameMode)
	{
		// 游戏模式未设置或类型不匹配，直接返回避免崩溃
		return;
	}
	//循环所有槽位
	for (const TTuple<int32,UMVVM_LoadSlot*> LoadSlot : LoadSlots)
	{
		//获取保存游戏数据,这个未来可以改成读取在线数据库的
		ULoadScreenSaveGame* SaveObject = BaseGameMode->GetSaveSlotData(LoadSlot.Value->GetLoadSlotName(), LoadSlot.Key);
		if (!SaveObject)
		{
			// 兜底：如果拿不到存档对象则跳过该槽位
			continue;
		}
		//从存档中获取保存槽状态，并赋值
		TEnumAsByte<ESaveSlotStatus> SaveSlotStatus = SaveObject->SaveSlotStatus;
		//从存档中取出玩家昵称
		const FString PlayerName = SaveObject->PlayerName;
		//从存档中取出玩家起始点标签
		const FName PlayerStartTag = SaveObject->PlayerStartTag;

		LoadSlot.Value->SlotStatus = SaveSlotStatus; //设置槽位状态
		LoadSlot.Value->SetPlayerName(PlayerName); //设置玩家昵称
		LoadSlot.Value->SetMapName(SaveObject->MapName); //设置地图名称
		LoadSlot.Value->SetPlayerLevel(SaveObject->PlayerLevel); //设置玩家等级
		LoadSlot.Value->PlayerStartTag = PlayerStartTag;//设置玩家起始点标签
		//初始化槽位
		LoadSlot.Value->InitializeSlot();
	}
}

//设置插槽数字
void UMVVM_LoadScreen::SetNumLoadSlots(int32 InNumLoadSlots)
{
	UE_MVVM_SET_PROPERTY_VALUE(NumLoadSlots, InNumLoadSlots);
}
